﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BaseClasses
{
    /// <summary>
    /// Link (ogniwo, powiązanie) contains two vertexes (Alfa and Omega) and path cost.
    /// </summary>
    public class Link : IUniqueObject
    {
        public int UniqueId
        {
            get
            {
                return this.uniqueId;
            }
        }
        readonly int uniqueId;

        /// <summary>
        /// Vertex Alfa.
        /// </summary>
        public Vertex Alfa { get { return this.alfa; } }
        readonly Vertex alfa;


        /// <summary>
        /// Vertex Omega.
        /// </summary>
        public Vertex Omega { get { return this.omega; } }
        readonly Vertex omega;


        /// <summary>
        /// Vertex cost.
        /// </summary>
        public int Cost { get { return this.cost; } }
        readonly int cost;


        /// <summary>
        /// 
        /// </summary>
        public Vertex[] Vertexes
        {
            get
            {
                Vertex[] vertexes = { alfa, omega };
                return vertexes;
            }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="alfa">Vertex alfa</param>
        /// <param name="omega">Vertex omega</param>
        /// <param name="cost">Link cost</param>
        public Link(Vertex alfa, Vertex omega, int cost)
        {
            if (alfa == null || omega == null)
                throw new ArgumentNullException("One of the vertexes is null");
            if (alfa == omega)
                throw new Exception("Both vertexes are the same.");

            this.uniqueId = UniqueIdGenerator.GetUniqueId();
            this.alfa = alfa;
            this.omega = omega;

            if (cost < 0)
                throw new ArgumentException("Cost has to be non-negative value");
            else
                this.cost = cost;
        }


        /// <summary>
        /// Looks the collection for the link with the same Alfa, Omega and cost. 
        /// </summary>
        /// <param name="collection">Collection</param>
        /// <param name="link">Link</param>
        public static bool ContainsLink(ICollection<Link> collection, Link link)
        {
            foreach (Link item in collection)
                if (item == link)
                    return true;
            return false;
        }

        #region ========== Operators ==========

        public static bool operator ==(Link l1, Link l2)
        {
            if ((object)l1 == null && (object)l2 == null)
                return true;

            if ((object)l1 == null || (object)l2 == null)
                return false;

            return l1.Alfa == l2.Alfa && l1.Omega == l2.Omega && l1.Cost == l2.Cost;
        }

        public static bool operator !=(Link l1, Link l2)
        {
            return !(l1 == l2);
        }

        #endregion

        public override string ToString()
        {
            return string.Format("{0} <-> {1}, Cost: {2}", this.alfa, this.omega, this.cost);
        }

    }
}
